<template>
  <el-dialog
    v-model="visible"
    :title="fileInfo?.fileName || '文件预览'"
    width="80%"
    top="5vh"
    @close="handleClose"
    class="preview-dialog"
  >
    <div class="preview-container">
      <!-- 加载状态 -->
      <div v-if="loading" class="loading-container">
        <el-icon class="is-loading" size="40"><RefreshRight /></el-icon>
        <p>加载中...</p>
      </div>
      <!-- 图片预览 -->
      <div v-else-if="!loading && previewType === 'image'" class="image-preview">
        <div class="image-controls">
          <el-button-group>
            <el-button @click="zoomOut" :disabled="scale <= 0.2">
              <el-icon><ZoomOut /></el-icon>
            </el-button>
            <el-button @click="resetScale">
              {{ Math.round(scale * 100) }}%
            </el-button>
            <el-button @click="zoomIn" :disabled="scale >= 3">
              <el-icon><ZoomIn /></el-icon>
            </el-button>
            <el-button @click="rotateLeft">
              <el-icon><RefreshLeft /></el-icon>
            </el-button>
            <el-button @click="rotateRight">
              <el-icon><RefreshRight /></el-icon>
            </el-button>
            <el-button @click="downloadFile">
              <el-icon><Download /></el-icon>
              下载
            </el-button>
          </el-button-group>
        </div>
        <div class="image-container" ref="imageContainer">
          <img
            :src="previewUrl"
            :style="{
              transform: `scale(${scale}) rotate(${rotation}deg)`,
              maxWidth: 'none',
              maxHeight: 'none'
            }"
            @load="handleImageLoad"
            @error="handleImageError"
            draggable="false"
          />
        </div>
      </div>

      <!-- 文本预览 -->
      <div v-else-if="!loading && previewType === 'text'" class="text-preview">
        <div class="text-controls">
          <el-button-group>
            <el-button @click="decreaseFontSize" :disabled="fontSize <= 10">
              A-
            </el-button>
            <el-button @click="resetFontSize">
              {{ fontSize }}px
            </el-button>
            <el-button @click="increaseFontSize" :disabled="fontSize >= 24">
              A+
            </el-button>
            <el-button @click="downloadFile">
              <el-icon><Download /></el-icon>
              下载
            </el-button>
          </el-button-group>
        </div>
        <div class="text-container" :style="{ fontSize: fontSize + 'px' }">
          <pre v-if="textContent">{{ textContent }}</pre>
          <div v-else class="loading-text">加载中...</div>
        </div>
      </div>

      <!-- PDF预览 -->
      <div v-else-if="!loading && previewType === 'pdf'" class="pdf-preview">
        <div class="pdf-controls">
          <el-button-group>
            <el-button @click="downloadFile">
              <el-icon><Download /></el-icon>
              下载
            </el-button>
            <el-button @click="openInNewTab" v-if="previewUrl">
              <el-icon><FullScreen /></el-icon>
              新窗口打开
            </el-button>
          </el-button-group>
        </div>
        <div class="pdf-container">
          <iframe
            v-if="previewUrl"
            :src="previewUrl"
            width="100%"
            height="600px"
            frameborder="0"
          ></iframe>
          <div v-else class="loading-pdf">PDF加载中...</div>
        </div>
      </div>

      <!-- 不支持预览的文件 -->
      <div v-else-if="!loading && previewType === 'unsupported'" class="unsupported-preview">
        <div class="unsupported-content">
          <el-icon :size="80" color="#ccc"><Document /></el-icon>
          <h3>此文件类型不支持预览</h3>
          <p>文件名：{{ fileInfo?.fileName }}</p>
          <p>文件大小：{{ formatFileSize(fileInfo?.fileSize || 0) }}</p>
          <p>文件类型：{{ fileInfo?.fileType }}</p>
          <el-button type="primary" @click="downloadFile" size="large">
            <el-icon><Download /></el-icon>
            下载文件
          </el-button>
        </div>
      </div>

      <!-- 预览错误 -->
      <div v-else-if="!loading && previewError && !previewUrl" class="preview-error">
        <div class="error-content">
          <el-icon :size="80" color="#f56c6c"><Warning /></el-icon>
          <h3>预览失败</h3>
          <p>{{ previewError }}</p>
          <el-button type="primary" @click="downloadFile">
            <el-icon><Download /></el-icon>
            下载文件
          </el-button>
        </div>
      </div>
    </div>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, computed, watch, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import {
  ZoomIn,
  ZoomOut,
  RefreshLeft,
  RefreshRight,
  Download,
  Document,
  Warning,
  FullScreen
} from '@element-plus/icons-vue'
import { generatePreviewUrl, generateDownloadUrl } from '@/api/file'
import type { FileInfo } from '@/api/file'

// Props 和 Emits
interface Props {
  modelValue: boolean
  fileInfo: FileInfo | null
}

interface Emits {
  (e: 'update:modelValue', value: boolean): void
}

const props = defineProps<Props>()
const emit = defineEmits<Emits>()

// 响应式数据
const visible = ref(false)
const loading = ref(false)
const previewUrl = ref('')
const textContent = ref('')
const previewError = ref('')

// 图片预览控制
const scale = ref(1)
const rotation = ref(0)
const imageContainer = ref<HTMLElement>()

// 文本预览控制
const fontSize = ref(14)
const currentPreviewType = ref<string>('')

// 预览类型判断
const previewType = computed(() => {
  // 如果后端设置了当前预览类型，使用它
  if (currentPreviewType.value) return currentPreviewType.value
  if (!props.fileInfo) return 'unsupported'

  const fileName = props.fileInfo.fileName.toLowerCase()
  const ext = fileName.split('.').pop()

  if (!ext) return 'unsupported'

  // 图片类型
  const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp']
  if (imageTypes.includes(ext)) return 'image'

  // 文本类型
  const textTypes = ['txt', 'md', 'json', 'xml', 'csv', 'log']
  if (textTypes.includes(ext)) return 'text'

  // PDF类型
  if (ext === 'pdf') return 'pdf'

  return 'unsupported'
})

// 监听显示状态
watch(() => props.modelValue, (newVal) => {
  visible.value = newVal
  if (newVal && props.fileInfo) {
    initPreview()
  }
})

watch(visible, (newVal) => {
  emit('update:modelValue', newVal)
})

// 初始化预览
const initPreview = async () => {
  if (!props.fileInfo) return

  loading.value = true
  previewError.value = ''
  previewUrl.value = ''
  textContent.value = ''
  currentPreviewType.value = ''

  // 重置控制状态
  scale.value = 1
  rotation.value = 0
  fontSize.value = 14

  try {
    if (previewType.value === 'unsupported') {
      loading.value = false
      return
    }

    // 获取预览链接
    const previewInfo = await generatePreviewUrl(props.fileInfo.id)

    if (!previewInfo.supportPreview) {
      // 后端返回不支持预览，更新预览类型为不支持
      currentPreviewType.value = 'unsupported'
      loading.value = false
      return
    }

    previewUrl.value = previewInfo.previewUrl

    // 如果是文本文件，需要获取文本内容
    if (previewType.value === 'text') {
      await loadTextContent()
    }

  } catch (error: any) {
    previewError.value = error.message || '获取预览失败'
  } finally {
    loading.value = false
  }
}

// 加载文本内容
const loadTextContent = async () => {
  if (!previewUrl.value) return

  try {
    const response = await fetch(previewUrl.value)
    if (!response.ok) {
      throw new Error('获取文件内容失败')
    }
    textContent.value = await response.text()
  } catch (error: any) {
    previewError.value = error.message || '加载文本内容失败'
  }
}

// 图片控制方法
const zoomIn = () => {
  scale.value = Math.min(scale.value * 1.2, 3)
}

const zoomOut = () => {
  scale.value = Math.max(scale.value / 1.2, 0.2)
}

const resetScale = () => {
  scale.value = 1
}

const rotateLeft = () => {
  rotation.value -= 90
}

const rotateRight = () => {
  rotation.value += 90
}

const handleImageLoad = () => {
  // 图片加载完成，清除错误状态
  previewError.value = ''
}

const handleImageError = () => {
  previewError.value = '图片加载失败'
}

// 文本控制方法
const increaseFontSize = () => {
  fontSize.value = Math.min(fontSize.value + 2, 24)
}

const decreaseFontSize = () => {
  fontSize.value = Math.max(fontSize.value - 2, 10)
}

const resetFontSize = () => {
  fontSize.value = 14
}

// PDF控制方法
const openInNewTab = () => {
  if (previewUrl.value) {
    window.open(previewUrl.value, '_blank')
  }
}

// 下载文件
const downloadFile = async () => {
  if (!props.fileInfo) return

  try {
    const downloadInfo = await generateDownloadUrl(props.fileInfo.id)

    const link = document.createElement('a')
    link.href = downloadInfo.downloadUrl
    link.download = props.fileInfo.fileName
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)

    ElMessage.success('开始下载')
  } catch (error: any) {
    ElMessage.error(error.message || '下载失败')
  }
}

// 格式化文件大小
const formatFileSize = (size: number): string => {
  if (size < 1024) return size + ' B'
  if (size < 1024 * 1024) return (size / 1024).toFixed(2) + ' KB'
  if (size < 1024 * 1024 * 1024) return (size / (1024 * 1024)).toFixed(2) + ' MB'
  return (size / (1024 * 1024 * 1024)).toFixed(2) + ' GB'
}

// 关闭对话框
const handleClose = () => {
  visible.value = false
}
</script>

<style scoped>
.preview-dialog {
  .el-dialog {
    max-width: 1200px;
  }

  .el-dialog__body {
    padding: 10px 20px;
  }
}

.preview-container {
  min-height: 400px;
  display: flex;
  flex-direction: column;
}

.loading-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 400px;
  color: #666;
}

.loading-container p {
  margin-top: 20px;
  font-size: 16px;
}

/* 图片预览样式 */
.image-preview {
  display: flex;
  flex-direction: column;
  height: 70vh;
}

.image-controls {
  padding: 10px 0;
  text-align: center;
  border-bottom: 1px solid #eee;
  margin-bottom: 10px;
}

.image-container {
  flex: 1;
  overflow: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f5f5f5;
  position: relative;
}

.image-container img {
  transition: transform 0.3s ease;
  cursor: grab;
}

.image-container img:active {
  cursor: grabbing;
}

/* 文本预览样式 */
.text-preview {
  display: flex;
  flex-direction: column;
  height: 70vh;
}

.text-controls {
  padding: 10px 0;
  text-align: center;
  border-bottom: 1px solid #eee;
  margin-bottom: 10px;
}

.text-container {
  flex: 1;
  overflow: auto;
  background: #f9f9f9;
  border: 1px solid #eee;
  border-radius: 4px;
}

.text-container pre {
  margin: 0;
  padding: 20px;
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  line-height: 1.5;
  white-space: pre-wrap;
  word-wrap: break-word;
}

.loading-text {
  text-align: center;
  color: #999;
  padding: 40px;
}

/* PDF预览样式 */
.pdf-preview {
  display: flex;
  flex-direction: column;
}

.pdf-controls {
  padding: 10px 0;
  text-align: center;
  border-bottom: 1px solid #eee;
  margin-bottom: 10px;
}

.pdf-container {
  display: flex;
  justify-content: center;
}

.loading-pdf {
  text-align: center;
  color: #999;
  padding: 40px;
}

/* 不支持预览和错误样式 */
.unsupported-preview,
.preview-error {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 400px;
}

.unsupported-content,
.error-content {
  text-align: center;
  color: #666;
}

.unsupported-content h3,
.error-content h3 {
  margin: 20px 0 10px;
  color: #333;
}

.unsupported-content p,
.error-content p {
  margin: 5px 0;
  color: #999;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .preview-dialog .el-dialog {
    width: 95% !important;
    margin: 0 !important;
  }

  .image-preview,
  .text-preview {
    height: 60vh;
  }

  .image-controls,
  .text-controls,
  .pdf-controls {
    padding: 5px 0;
  }

  .el-button-group .el-button {
    padding: 8px 12px;
  }
}
</style>